package com.acme.bankapp.domain.email.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


import com.acme.bankapp.domain.email.Email;
import com.acme.bankapp.domain.email.Queue;

public class QueueImpl implements Queue {
	List<Email> mails = new ArrayList<Email>();
	private int maxsize;
	private Lock lock = new ReentrantLock();
	private Condition readconditon  = lock.newCondition();
	private Condition writeconditon = lock.newCondition();
	private boolean close;

	public QueueImpl(int maxsize) {
		this();
		this.maxsize = maxsize;
	}

	public QueueImpl() {}
	
	public void addEmail(Email email) throws InterruptedException {	
		lock.lock();
		try {
			if (close) {
				System.out.println("Mail is ignored, queue is closed");
				return;
			}
			while (mails.size() >= this.maxsize)
				writeconditon.await();

			mails.add(email);
			readconditon.signal();
		} finally {
			lock.unlock();
		}
	}

	public Email getEmail() throws InterruptedException {
		lock.lock();
		try {
			if (close) {
				System.out.println("Can't get mail, queue is closed");
				return null;
			}
			while (mails.isEmpty()) 
				readconditon.await();
			writeconditon.signal();
			return mails.remove(0);
		} finally {
			lock.unlock();
		}

	}

	public void close() {
		lock.lock();
		try {
			close = true;
		} finally {
			lock.unlock();
		}
	}
	
	public static void main(String[] args) {
		final QueueImpl queue = new QueueImpl(10);
		
		Thread t1 = new Thread() {
			@Override
			public void run() {
				for (int i = 0; i < 7; i++) {
				try {
					Email email = queue.getEmail();
					System.out.println(email.toString());
				} catch (InterruptedException e) {}
				}
			}
			
		};
		
		t1.start();
		
		Thread t2 = new Thread() {
			@Override
			public void run() {
				for (int i = 0; i < 5; i++) {
					Email email = new EmailImpl();
					email.setFrom("User_" + new Random().nextDouble());
					email.setTo("To_" + new Random().nextDouble());
					email.setSubject("Subject_" + new Random().nextDouble());
					email.setMessage("Message_" + new Random().nextDouble());

					try {
						queue.addEmail(email);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}

			}
		};
		
		t2.start();
		
//		try {
//			Thread.sleep(1000);
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
		queue.close();
		
	}
}